<?php
/**
 * Baseollect.php
 *
 * PHP Version 5.6
 *
 * @category PHP
 * @package  Collector
 * @author   ctwj <908504609@qq.com>
 * @license  MIT https://mit-license.org/
 * @link     MIT https://mit-license.org/
 * @date     2018-05-13 22:56:47
 * @modifyby ctwj
 */

namespace Telegram\Collector;

use Telegram\Collector\CollectInterface;
use GuzzleHttp\Client;

/**
 * Collect Base class
 *
 * @category PHP
 * @package  Collector
 * @author   ctwj <908504609@qq.com>
 * @license  MIT https://mit-license.org/
 * @link     MIT https://mit-license.org/
 */
class BaseCollect
{
    public $resource;
    /**
     * Xpath Obj
     *
     * @var [DOMXPath]
     */
    private $xpathObj;

    /**
     * 加载资源配置
     *
     * @param [\Telegram\Object\Resource] $resource 资源Resource对象
     *
     * @return void
     */
    public function loadconfig($resource)
    {
        $this->resource = $resource;
    }

    /**
     * 对采集到的数据进行整理
     *
     * @param [type] $data 需要处理的数据
     *
     * @return array
     */
    public function dataFix($data)
    {
        $extinfo = $this->resource->extinfo;
        if (is_null($extinfo)) {
            return $data;
        }

        $temp_data = $data;
        $result = [];

        // fetch pattern
        if (isset($extinfo['fetch_url']) && $extinfo['fetch_url'] && $extinfo['fetch_pat']) {
            foreach ($temp_data as $item) {
                $item = $this->_fetchPattern($item, $extinfo['fetch_pat']);
                $result[] = $item;
            }
            $temp_data = $result;
        }

        // data filter
        if (isset($extinfo['data_filter']) && is_array($extinfo['data_filter']) && count($extinfo['data_filter'])) {
            $result = [];
            foreach ($temp_data as $item) {
                $item = $this->_dataFilter($item, $extinfo['data_filter']);
                $result[] = $item;
            }
        }

        return $result;
    }

    /**
     * data fetch
     *
     * @param [array] $message 数据
     * @param [array] $patinfo 提取规则
     *
     * @return void
     */
    private function _fetchPattern($message, $patinfo)
    {
        $result = $message;
        $url = $message['link'];
        $content = '';

        // 获取网页内容
        try {
            $client = new \GuzzleHttp\Client([
                'headers' => ['User-Agent' => getUserAgent()]
            ]);
            $response = $client->get($url);
            $content = $response->getBody()->__toString();

            if (empty(trim($content))) {
                return $result;
            }
        } catch (\Exception $e) {
            \getService('logger')->warning('Fetch Content fail', ['url' => $url, 'error' => $e->getMessage()]);
            return $result;
        }

        // 初始化 xpath
        $this->_createXpathObj($content, $patinfo);
      
        
        // 提取数据
        foreach ($patinfo as $field => $filter) {
            if ($filter['type'] == 'reg' && preg_match($filter['pattern'], $content, $matches)
                && isset($matches[$filter['position']]) && !empty($matches[$filter['position']])
            ) {
                $result[$field] = $matches[$filter['position']];
            }
            if ($filter['type'] == 'xpath' && ! empty($filter['pattern'])) {
                $result[$field] = $this->_getXpathField($filter['pattern']);
            }
        }

        return $result;
    }

    /**
     * 数据过滤
     *
     * @param [array] $message 数据
     * @param [array] $rules   过滤规则
     *
     * @return void
     */
    private function _dataFilter($message, $rules)
    {
        $data = $message;
        foreach ($rules as $pat) {
            // 进行正则替换
            if (isset($pat['field']) && $pat['pattern'] && isset($pat['replace_str'])) {
                try {
                    $data[$pat['field']] = preg_replace($pat['pattern'], $pat['replace_str'], $data[$pat['field']]);
                } catch (\Exception $e) {
                    \getService('logger')->warning(
                        'Invalid Resource extinfo',
                        ['pattern' => $pat['pattern'],'error' => $e->getMessage()]
                    );
                }
            }
        }
        return $data;
    }

    /**
     * Get first pic url
     *
     * @param [type] $content
     * @return void
     */
    public function parseFirstPic($content, $url)
    {
        if (empty(trim($content))) {
            return '';
        }
        $pat = '/<img(.*?)src=\"(.+?)\".*?>/';
        if (!preg_match($pat, $content, $matches) || !isset($matches[2])) {
            return '';
        }
        $pic = trim($matches[2]);
        if (!preg_match('/^https?:\/\/.*?$/i', $pic, $matches)) {
            if (preg_match('/(^https?:\/\/.*?\/)/i', $url, $matches)) {
                $pic = $matches[1] . $pic;
            }
        }
        return $pic;
    }

    /**
     * 获取Xpath解析值
     *
     * @param [type] $pat 匹配模式
     *
     * @return string
     */
    private function _getXpathField($pat)
    {
        $objs = $this->xpathObj->query($pat);
        if ($objs->length > 0) {
            $node = $objs->item(0);
            $outerHTML = $node->ownerDocument->saveHTML($node);
            return trim($outerHTML);
        }
        return '';
    }

    /**
     * 初始化XpathObj对象
     *
     * @param [type]  $content  网页内容
     * @param [array] $pathinfo 匹配信息
     *
     * @return void
     */
    private function _createXpathObj($content, $patinfo)
    {
        // 如果没有xpath配置项，不初始化xpath
        if (!$this->_existsXpathParse($patinfo)) {
            return;
        }
        try {
            $dom = new \DOMDocument();
            @$dom->loadHtml($content);
            $dom->normalize();
            $xpath = new \DOMXpath($dom);
            $this->xpathObj = $xpath;
        } catch (\Exception $e) {
            getService('logger')->warning('Parse html fail', ['content' => $content]);
        }
    }

    /**
     * 判断是否需要初始化Xpath
     *
     * @return bool
     */
    private function _existsXpathParse($fetch_pat)
    {
        if (isset($fetch_pat) && is_array($fetch_pat)) {
            foreach ($fetch_pat as $item) {
                if ($item['type'] == 'xpath') {
                    return true;
                }
            }
        }
        return false;
    }
}
